#include "globals.h"

void 
print_ack_array(
        int arr[],
        int size
        )
{
    int ix = 0;

    printf("\n>>>> ACK ARRAY >>>>>>>>\n");

    for (ix = 0; ix < size; ix++)
    {
        printf("%d\t", arr[ix]);
    }

    printf("\n>>>>> ACK ARRAY END >>>>>>>\n");
}

int 
done_receiving_acks(
        int arr[],
        int size
        )
{
    int ix = 0;

    for (ix = 0; ix < size; ix++)
    {
        if (arr[ix] == 0)
        {
            return FALSE;
        }
    }

    return TRUE;
}

int 
calc_slide(
        int arr[],
        int size
        )
{
    int ix = 0;

    for (ix = 0; ix < size; ix++)
    {
        if (arr[ix] == 0)
        {
            break;
        }
    }

    return (ix+1);
}

void
reset_ack_flags(
        int arr[],
        int size
        )
{
    int ix = 0;

    for (ix = 0; ix < size; ix++)
    {
        arr[ix] = 0;
    }
}

void
send_window(
        int fd,
        int flags,
        arq_params* win,
        datagram_list* head,
        int ack_array[],
        int slide_val
        )
{
    int ix;
    datagram* dg_send;

    for (ix = win->win_l; ix <= win->win_r; ix++)
    {
        if (ack_array[(ix - slide_val) % win->win_size] == 0)
        {
            dg_send = find_datagram(head, ix);
            log_msg_int("sending ", dg_send->seq_num);
            send(fd, dg_send, sizeof(*dg_send), flags);
        }
    }
}

int 
fill_window(
        arq_params* win,
        datagram_list* head,
        int fd,
        int * eof_reached
        )
{
    datagram* dg;
    int n;
    int count = 0;

    if (*eof_reached == TRUE)
    {
        return 0;
    }

    while (win->win_r < win->win_l + win->win_size - 1)
    {
        count ++;

        dg = (datagram*) malloc(sizeof(datagram));
        n = read(fd, dg->data, MAX_DATAGRAM_BUF_SIZE);

        if (n < MAX_DATAGRAM_BUF_SIZE || n == 0)
        {
            //
            // nothing more to read from the file.
            //

            dg->data[n] = EOF;
            append_buffer(head, dg);
            win->win_r = head->dgram->seq_num;
            *eof_reached = TRUE;
            log_msg_int("fill window", count);
            log_msg_int_int("left right", win->win_l, win->win_r);
            log_msg(dg->data);

            break;
        }

        append_buffer(head, dg);
        win->win_r = head->dgram->seq_num;
    }

    return count;
}

int 
slide(
        arq_params* win,
        int ack_array[]
     )
{
    int ix;
    int slide_val = 0;
    int jx;

    for (ix = 0; ix < win->win_size; ix++)
    {
        if (ack_array[ix] == 0)
        {
            break;
        }

        slide_val++;
    }

    log_msg_int("slide: ", slide_val);

    if (slide_val == 0)
    {
        return 0;
    }

    jx = 0;

    for (ix = slide_val; ix < win->win_size; ix++)
    {
        ack_array[jx++] = ack_array[ix];
    }

    for (; jx < win->win_size; jx++)
    {
        ack_array[jx] = 0;
    }

    win->win_l += slide_val;
    return slide_val;
}

int 
should_slide(
        int arr[],
        int size
        )
{
    int ix = 0;
    int one_pos = size;
    int zero_pos = size;

    for (ix = 0; ix < size; ix ++)
    {
        if (arr[ix] == 1)
        {
            one_pos = ix;
            break;
        }
    }

    for (ix = 0; ix < size; ix ++)
    {
        if (arr[ix] == 0)
        {
            zero_pos = ix;
            break;
        }
    }

    if (one_pos < zero_pos)
    {
        return TRUE;
    }

    return FALSE;
}

int 
stop_sending(
        int eof_reached,
        int ack_num,
        int win_r
        )
{
    if (eof_reached == FALSE)
    {
        return FALSE;
    }

    if (win_r != ack_num)
    {
        return FALSE;
    }

    return TRUE;
}

void
print_window_params(
        arq_params win
        )
{
    printf("\n>>WIN PARAMS>>\nwindow size: %d\nwindow_left: %d\nwindow_right: %d\n>>\n", 
            win.win_size, win.win_l, win.win_r);
}

